package com.mfc.education.service.ucenter.controller.api;

import com.google.gson.Gson;
import com.mfc.education.common.base.result.ResultCodeEnum;
import com.mfc.education.common.base.util.ExceptionUtils;
import com.mfc.education.common.base.util.HttpClientUtils;
import com.mfc.education.common.base.util.JwtInfo;
import com.mfc.education.common.base.util.JwtUtils;
import com.mfc.education.service.base.exception.EduException;
import com.mfc.education.service.ucenter.entity.Member;
import com.mfc.education.service.ucenter.service.MemberService;
import com.mfc.education.service.ucenter.util.UcenterProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author mfc
 * @since 2021/10/2
 */

@Controller
@RequestMapping("/api/ucenter/wx")
@Slf4j
public class ApiWxController {

    @Autowired
    private UcenterProperties ucenterProperties;

    @Autowired
    private MemberService memberService;

    /**
     * 微信扫码登陆
     *
     * @param session
     * @return
     */
    @GetMapping("login")
    public String genQrConnect(HttpSession session) {
        //组装url：https://open.weixin.qq.com/connect/qrconnect?appid=wx1b4c7610fc671845&redirect_uri=https%3A%2F%2Faccount.geekbang.org%2Faccount%2Foauth%2Fcallback%3Ftype%3Dwechat%26ident%3D2869f4%26login%3D0%26cip%3D0%26redirect%3Dhttps%253A%252F%252Faccount.geekbang.org%252Fthirdlogin%253Fremember%253D1%2526type%253Dwechat%2526is_bind%253D0%2526platform%253Dtime%2526redirect%253Dhttps%25253A%25252F%25252Fwww.geekbang.org%25252F%2526failedurl%253Dhttps%253A%252F%252Faccount.geekbang.org%252Fsignin%253Fredirect%253Dhttps%25253A%25252F%25252Fwww.geekbang.org%25252F&response_type=code&scope=snsapi_login&state=21cde472e337393e26486a4dd3145237#wechat_redirect
        String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";

        String redirectUri = "";
        try {
            redirectUri = URLEncoder.encode(ucenterProperties.getRedirectUri(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error(ExceptionUtils.getMessage(e));
            throw new EduException(ResultCodeEnum.URL_ENCODE_ERROR);
        }

        //生产随机数state,防止csrf
        String state = UUID.randomUUID().toString();

        session.setAttribute("wx_open_state", state);

        String qrcodeUrl = String.format(baseUrl, ucenterProperties.getAppId(), redirectUri, state);


        //跳转到组装的url地址中去
        return "redirect:" + qrcodeUrl;
    }

    @GetMapping("callback")
    public String callback(HttpSession session, String code, String state) {

        //回调被拉起，并获得code和state参数
        System.out.println("callback被调用");
        System.out.println("code = " + code);
        System.out.println("state = " + state);


        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(state)) {
            log.error("非法回调请求");
            throw new EduException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
        }

        String sessionState = (String) session.getAttribute("wx_open_state");
        if (!state.equals(sessionState)) {
            log.error("非法回调请求");
            throw new EduException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
        }

        String accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
        // 组将url的参数https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
        Map<String, String> params = new HashMap<>();
        params.put("appid", ucenterProperties.getAppId());
        params.put("secret", ucenterProperties.getAppSecret());
        params.put("code", code);
        params.put("grant_type", "authorization_code");

        HttpClientUtils httpClientUtils = new HttpClientUtils(accessTokenUrl, params);

        String result = "";
        try {
            httpClientUtils.get();

            result = httpClientUtils.getContent();

            log.info("result=" + result);
        } catch (Exception e) {
            log.error("获取access_token失败");
            throw new EduException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
        }

        Gson gson = new Gson();
        HashMap<String, Object> resultMap = gson.fromJson(result, HashMap.class);

        Object errcodeObj = resultMap.get("errcode");
        if (errcodeObj != null) {
            String errmsg = (String) resultMap.get("errmsg");
            Double errcode = (Double) errcodeObj;
            log.error("获取access_token失败 - " + "message: " + errmsg + ", errcode: " + errcode);
            throw new EduException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
        }
        String openid = (String) resultMap.get("openid");
        String accessToken = (String) resultMap.get("access_token");
        log.info("accessToken = " + accessToken);
        log.info("openid = " + openid);


        //在本地数据库中查找当前微信用户的信息


        Member member = memberService.getByOpenid(openid);
        //if:如果当前用户不存在，则去微信的资源服务器获取用户个人信息（携带access_token）
        if (member == null) {
            String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo";
            Map<String, String> map = new HashMap<>();
            map.put("access_token", accessToken);
            map.put("openid", openid);
            HttpClientUtils httpClientUserInfo = new HttpClientUtils(userInfoUrl, map);
            String userInfos = "";
            try {
                httpClientUserInfo.get();
                userInfos = httpClientUserInfo.getContent();
            } catch (Exception e) {
                log.error("获取用户信息失败");
                throw new EduException(ResultCodeEnum.FETCH_USERINFO_ERROR);
            }

            //解析出结果中的用户个人信息
            HashMap<String, Object> userInfoMap = gson.fromJson(userInfos, HashMap.class);
            Object userInfoErrcode = userInfoMap.get("errcode");
            if (userInfoErrcode != null) {
                String errmsg = (String) resultMap.get("errmsg");
                Double errcode = (Double) errcodeObj;
                log.error("获取用户信息失败 - " + "message: " + errmsg + ", errcode: " + errcode);
                throw new EduException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
            }
            String nickname = (String) userInfoMap.get("nickname");
            Double sex = (Double) userInfoMap.get("sex");
            String avatar = (String) userInfoMap.get("headimgurl");

            // 在本地数据库中插入当前微信用户的信息（使用微信账号在本地服务器注册新用户)
            member = new Member();
            member.setOpenid(openid);
            member.setNickname(nickname);
            member.setSex(sex.intValue());
            member.setAvatar(avatar);

            memberService.save(member);


        }
        //使用当前用户的信息登录(生成jwt）
        //else:如果当前用户已存在，则直接使用当前用户的信息登录（生成jwt〉
        JwtInfo jwtInfo = new JwtInfo();
        jwtInfo.setId(member.getId());
        jwtInfo.setNickname(member.getNickname());
        jwtInfo.setAvatar(member.getAvatar());
        String jwtToken = JwtUtils.getJwtToken(jwtInfo, 1800);

        return "redirect:http://localhost:3000?token=" + jwtToken;
    }


}
